<?php
// 应用公共文件

/**
 * 获取模块配置信息
 *
 * @param string $module_name   模块名称
 * @param string $config_name   配置名称，多级配置使用.分隔，例如 configGroup.configName
 * @param string $default_value 默认值
 *
 * @return mixed
 */
function get_module_config(string $module_name, string $config_name = '', string $default_value = ''): mixed
{
    return get_config($module_name, $config_name, $default_value);
}

/**
 * 返回插件配置信息
 *
 * @param string $plugin_name   插件名称
 * @param string $config_name   配置名称，多级配置使用.分隔，例如 configGroup.configName
 * @param string $default_value 默认值
 *
 * @return mixed
 */
function get_plugin_config(string $plugin_name, string $config_name = '', string $default_value = ''): mixed
{
    return get_config($plugin_name, $config_name, $default_value, true);
}

/**
 * 返回模块或插件的配置信息
 */
function get_config(string $module_name, string $config_name = '', string $default_value = '', bool $is_plugin = false): mixed
{
    return $default_value || '';
}


/**
 * 字符串转换为数组，主要用于把分隔符调整到第二个参数
 *
 * @param array|string $str  要分割的字符串
 * @param string       $glue 分割符
 *
 * @return array
 */
function stringToArrayFun(array|string $str, string $glue = ','): array
{
    if (empty($glue)) $glue = ',';
    if (is_array($str)) return $str;
    if ($str == '' || empty($str)) return [];
    if (strpos($str, $glue) > 0) {
        return explode($glue, $str);
    } else {
        return [$str];
    }
}

/**
 * 数组转换为字符串，主要用于把分隔符调整到第二个参数
 *
 * @param array|string $arr  要连接的数组
 * @param string       $glue 分割符
 *
 * @return string
 */
function arrayToStringFun(array|string $arr, string $glue = ','): string
{
    if (!is_array($arr)) return $arr;
    return implode($glue, $arr);
}


/**
 * 字符串加解密
 *
 * @param string  $string    要加解密的原始字符串
 * @param string  $operation 加密：ENCODE，解密：DECODE
 * @param string  $key       密钥
 * @param integer $expiry    有效期
 *
 * @return string
 */
function getRandStringFun(string $string, string $operation = 'DECODE', string $key = '', int $expiry = 0): string
{
    $ckey_length   = 4;
    $key           = md5($key ? $key : config('hs_auth.key'));
    $keya          = md5(substr($key, 0, 16));
    $keyb          = md5(substr($key, 16, 16));
    $keyc          = $operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length);
    $cryptkey      = $keya . md5($keya . $keyc);
    $key_length    = strlen($cryptkey);
    $string        = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
    $string_length = strlen($string);

    $result = '';
    $box    = range(0, 255);
    $rndkey = [];
    for ($i = 0; $i <= 255; $i++) {
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);
    }

    for ($j = $i = 0; $i < 256; $i++) {
        $j       = ($j + $box[$i] + $rndkey[$i]) % 256;
        $tmp     = $box[$i];
        $box[$i] = $box[$j];
        $box[$j] = $tmp;
    }

    for ($a = $j = $i = 0; $i < $string_length; $i++) {
        $a       = ($a + 1) % 256;
        $j       = ($j + $box[$a]) % 256;
        $tmp     = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        $result  .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }

    if ($operation == 'DECODE') {
        if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
            return substr($result, 26);
        } else {
            return '';
        }
    } else {
        return $keyc . str_replace('=', '', base64_encode($result));
    }
}

/**
 * 数字金额转换成中文大写金额的函数
 *
 * @param float|int $num 待转换的数字
 *
 * @return string
 */
function numberToRmbFun(float|int $num = 0): string
{
    if ($num == 0) return '零元整';
    $c1 = '零壹贰叁肆伍陆柒捌玖';
    $c2 = '分角元拾佰仟万拾佰仟亿';
    //精确到分后面就不要了，所以只留两个小数位
    $num = round($num, 2);
    //将数字转化为整数
    $num = $num * 100;
    if (strlen($num) > 10) {
        return '金额太大，请检查';
    }
    $i = 0;
    $c = '';
    while (1) {
        if ($i == 0) {
            //获取最后一位数字
            $n = substr($num, strlen($num) - 1, 1);
        } else {
            $n = $num % 10;
        }
        //每次将最后一位数字转化为中文
        $p1 = substr($c1, 3 * $n, 3);
        $p2 = substr($c2, 3 * $i, 3);
        if ($n != '0' || ($n == '0' && ($p2 == '亿' || $p2 == '万' || $p2 == '元'))) {
            $c = $p1 . $p2 . $c;
        } else {
            $c = $p1 . $c;
        }
        $i = $i + 1;
        //去掉数字最后一位了
        $num = $num / 10;
        $num = (int)$num;
        //结束循环
        if ($num == 0) {
            break;
        }
    }
    $j    = 0;
    $slen = strlen($c);
    while ($j < $slen) {
        //utf8一个汉字相当3个字符
        $m = substr($c, $j, 6);
        //处理数字中很多0的情况,每次循环去掉一个汉字“零”
        if ($m == '零元' || $m == '零万' || $m == '零亿' || $m == '零零') {
            $left  = substr($c, 0, $j);
            $right = substr($c, $j + 3);
            $c     = $left . $right;
            $j     = $j - 3;
            $slen  = $slen - 3;
        }
        $j = $j + 3;
    }
    //这个是为了去掉类似23.0中最后一个“零”字
    if (substr($c, strlen($c) - 3, 3) == '零') {
        $c = substr($c, 0, strlen($c) - 3);
    }
    //将处理的汉字加上“整”
    if (empty($c)) {
        return '零元整';
    } else {
        return $c . '整';
    }
}


/**
 * 格式化字节大小
 *
 * @param number $size      字节数
 * @param string $delimiter 数字和单位分隔符
 *
 * @return string            格式化后的带单位的大小
 */
function formatBytesFun($size, string $delimiter = ''): string
{
    $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
    for ($i = 0; $size >= 1024 && $i < 5; $i++) $size /= 1024;
    return round($size, 2) . $delimiter . $units[$i];
}

/**
 * 制作签名
 *
 * @param array $params     签名数组
 * @param false $urlencoded 是否URL编码
 * @param array $extend     扩展信息
 *
 * @return string
 */
function makeSignature(array $params = [], false $urlencoded = false, array $extend = []): string
{
    foreach ($params as $k => $v) {
        $Parameters[$k] = $v;
    }
    //签名步骤一：按字典序排序参数
    ksort($Parameters);
    $buff = [];
    foreach ($Parameters as $k => $v) {
        if ($urlencoded) {
            $v = urlencode($v);
        }
        $buff[] = "{$k}={$v}";
    }
    $String = arrayToStringFun($buff, '&');
    if (!empty($extend)) {
        $String .= arrayToStringFun($extend, '');
    }
    return md5($String);
}

/**
 * 获取数组深度
 * @param array $array
 *
 * @return int
 */
function getArrayDepthCount(array $array): int
{
    // 如果数组为空，返回0
    if (empty($array)) {
        return 0;
    }
    // 初始化最大深度为1
    $maxDepth = 1;
    // 遍历数组中的每个元素
    foreach ($array as $value) {
        // 如果元素是数组，则递归调用getArrayDepth
        if (is_array($value)) {
            // 计算当前子数组的深度，并与当前最大深度比较
            $depth = 1 + getArrayDepthCount($value);
            if ($depth > $maxDepth) {
                $maxDepth = $depth;
            }
        }
    }
    return $maxDepth;
}

/**
 * 转换模型查询条件,如果是一维数组，则转换成二维数组
 */
function convertModelCondition(array $condition = []): array
{
    if (is_array($condition) && getArrayDepthCount($condition) == 1) {
        $condition = [$condition];
    }
    return $condition;
}
